package cn.micai.base.thread;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 描述：多线程售票案例
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/6/1 17:25
 */
public class SellTicket {

    private static final Logger logger = LoggerFactory.getLogger(SellTicket.class);

    public static void main(String [] args) {
        MyThread unit = new MyThread();  //售票线程单元
        //六个售票窗口同时售票5000张
        logger.info("开始售票：{}========================");
        new Thread(unit,"【窗口一】").start();
        new Thread(unit,"【窗口二】").start();
        new Thread(unit,"【窗口三】").start();
        new Thread(unit,"【窗口四】").start();
        new Thread(unit,"【窗口五】").start();
        new Thread(unit,"【窗口六】").start();
    }

    /**
     * 创建线程单元：一个线程单元模拟一个售票窗口进行售票，每执行一次售出票数+1
     */
    static class MyThread implements Runnable {

        private static Object lock = new Object(); //静态锁
        private int votes = 1; //日预售票数起点

        // 售票
        @Override
        public void run() {
            while (true) {
                // 1.用lock静态锁把锁的粒度缩小，提供并发效率
                // 2.synchronized(MyThread.class);把整个类锁住，这样很糟糕并且效率低下。比如调用其他方法，也要等得到锁才能继续做。
                synchronized (lock) { // 同步锁：保证在同一时刻最多只有一个线程单元进行售票
                    if (votes > 5000) {
                        //日售票数已售完
                        System.out.println("票已经售完");
                        break;
                    }
                    System.out.println(Thread.currentThread().getName() + "成功预订" + votes + "票");
                    votes++;
                }
            }
        }
    }
}
